package com.heima.behavior.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.behavior.service.BehaviorService;
import com.heima.client.article.IArticleClient;
import com.heima.common.exception.CustomException;
import com.heima.common.redis.CacheService;
import com.heima.model.common.dtos.LikesBehaviorDto;
import com.heima.model.common.dtos.ReadBehaviorDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.dtos.UnlikesBehaviorDto;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.common.pojos.article.AdArticleStatistics;
import com.heima.model.common.pojos.article.ApArticle;
import com.heima.model.common.pojos.user.ApUserUnlike;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
public class BehaviorServiceImpl implements BehaviorService {

    @Autowired
    private CacheService cacheService;
    @Autowired
    private IArticleClient articleClient;
    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    //点赞
    private static final String LIKES_BEHAVIOR = "like";
    //阅读
    private static final String READ_BEHAVIOR = "read";
    //不喜欢
    private static final String UN_LIKES_BEHAVIOR = "unlike";

    /**
     * 用户点赞
     *
     * @param behaviorDto
     * @return
     */
    @Override
    public ResponseResult likesBehavior(LikesBehaviorDto behaviorDto, String userId) {
        //1. 参数校验
        if (behaviorDto == null || behaviorDto.getArticleId() == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }

        //2. 查询数据库获取文章信息
        Long articleId = behaviorDto.getArticleId();
        ApArticle article = articleClient.getArticleById(articleId);
        if (article == null) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        String key = userId + "_" + articleId;
        String redisKey;

        //3 判断点赞类型
        switch (behaviorDto.getType()) {
            case 0:
                redisKey = LIKES_BEHAVIOR;
                break;
            case 1:
                redisKey = UN_LIKES_BEHAVIOR;
                break;
            case 2:
                redisKey = READ_BEHAVIOR;
                break;
            default:
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //4. 将从数据库获取的最新数据同步到redis
        //4.1 如果数据库的点赞数量，收藏数量，评论数量，阅读数量为null，给默认值0
        if (article.getLikes() == null) article.setLikes(0);
        if (article.getComment() == null) article.setComment(0);
        if (article.getViews() == null) article.setViews(0);
        if (article.getCollection() == null) article.setCollection(0);
        //4.2 将数据库的数据article存入redis
        cacheService.hPut(redisKey, key, JSON.toJSONString(article));

        //4.3 执行点赞/取消点赞
        if (behaviorDto.getOperation() == 0) { //点赞
            //点赞数量增加
            article.setLikes(article.getLikes() + 1);
        } else if (behaviorDto.getOperation() == 1) { //取消点赞
            //点赞数量减少
            article.setLikes(article.getLikes() - 1);
            cacheService.removeHashField(redisKey,key);
        }

        //4. 通知kafka
        Map<String, Object> map = new HashMap<>();
        //文章id
        map.put("articleId", articleId);
        //点赞数量
        map.put("likes", article.getLikes());
        kafkaTemplate.send("article_behavior_like", JSON.toJSONString(map));

        //5. 返回结果
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 用户阅读
     *
     * @param behaviorDto
     * @return
     */
    @Override
    public ResponseResult readBehavior(ReadBehaviorDto behaviorDto, String userId) {
        // 1. 参数校验
        if (behaviorDto == null || behaviorDto.getArticleId() == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }

        // 2. 查询数据库获取文章信息
        Long articleId = behaviorDto.getArticleId();
        ApArticle article = articleClient.getArticleById(articleId);
        if (article == null) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        String key = userId + "_" + articleId;
        String redisKey = READ_BEHAVIOR;

        // 3. 将从数据库获取的最新数据同步到redis
        if (article.getViews() == null) article.setViews(0);
        cacheService.hPut(redisKey, key, JSON.toJSONString(article));

        // 4. 增加阅读次数
        article.setViews(article.getViews() + 1);
        cacheService.hPut(redisKey, key, JSON.toJSONString(article));

        // 5. 通知kafka
        Map<String, Object> map = new HashMap<>();
        map.put("articleId", articleId);
        map.put("views", article.getViews());
        kafkaTemplate.send("article_behavior_read", JSON.toJSONString(map));

        // 6. 返回结果
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 用户不喜欢
     *
     * @param behaviorDto
     * @param userId
     * @return
     */
    @Override
    public ResponseResult unlikesBehavior(UnlikesBehaviorDto behaviorDto, String userId) {
        // 1. 参数校验
        if (behaviorDto == null || behaviorDto.getArticleId() == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }

        // 2. 获取文章ID
        Long articleId = behaviorDto.getArticleId();
        String key = userId + "_" + articleId;
        String redisKey = UN_LIKES_BEHAVIOR;

        // 3. 从 Redis 查询数据
        String value = null;
        try {
            value = (String) cacheService.hGet(redisKey, key);
        } catch (Exception e) {
            return ResponseResult.errorResult(AppHttpCodeEnum.ERROR);
        }

        if (value == null) {
            // 如果 Redis 中没有数据，初始化一个新的对象
            ApUserUnlike unlike = new ApUserUnlike();
            unlike.setArticleId(articleId);
            unlike.setUnlikeNum(0);//默认为0
            unlike.setType((short) 0);
            cacheService.hPut(redisKey, key, JSON.toJSONString(unlike));
        }

        // 4. 执行不喜欢/取消不喜欢操作
        if (behaviorDto.getType() == 1) { // 取消不喜欢
            //删除redis数据
            cacheService.hDelete(redisKey, key);
        }

        // 5. 返回结果
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }
}